package pl.lodz.p.beans.utils;

import hibernatingrhinos.hibernate.profiler.appender.HibernateProfiler;

import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.jmx.StatisticsService;
import org.hibernate.stat.CollectionStatistics;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;

public class HibernateUtil implements Serializable{

	private static final long serialVersionUID = 1024157631432514889L;
	
	private static SessionFactory sessionFactory = null;

	private static Statistics stats;
	
	private static SecondLevelCacheStatistics secondLevelCacheStatistics;
	
	public static Statistics getStats() {
		return stats;
	}

	public static void setStats(Statistics stats) {
		HibernateUtil.stats = stats;
	}

	public static SecondLevelCacheStatistics getSecondLevelCacheStatistics() {
		return secondLevelCacheStatistics;
	}

	public static void setSecondLevelCacheStatistics(
			SecondLevelCacheStatistics secondLevelCacheStatistics) {
		HibernateUtil.secondLevelCacheStatistics = secondLevelCacheStatistics;
	}

	public static CollectionStatistics getCollectionStatistics() {
		return collectionStatistics;
	}

	public static void setCollectionStatistics(
			CollectionStatistics collectionStatistics) {
		HibernateUtil.collectionStatistics = collectionStatistics;
	}

	private static CollectionStatistics collectionStatistics;
	
	public static SessionFactory getSessionFactory() {
		if(sessionFactory == null) {
			Configuration configuration = new Configuration();
			HibernateProfiler.configure(configuration);
			sessionFactory = configuration.configure().buildSessionFactory();
			HibernateProfiler.initialize();
		}
//		stats = sessionFactory.getStatistics();
//		secondLevelCacheStatistics = stats.getSecondLevelCacheStatistics("");
//		collectionStatistics = stats.getCollectionStatistics("");
//		stats.logSummary();
//		stats.setStatisticsEnabled(true);
//		
//		StatisticsService statsMBean = new StatisticsService();
//		statsMBean.setSessionFactory(sessionFactory);
//		statsMBean.setStatisticsEnabled(true);
//
//		MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
//		try {
//			mBeanServer.registerMBean(statsMBean, new ObjectName("Hibernate:application=Statistics"));
//		} catch (InstanceAlreadyExistsException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (MBeanRegistrationException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (NotCompliantMBeanException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (MalformedObjectNameException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		return sessionFactory;
	}
	
	public void init(){
//		try {
//			//initStatistics(HibernateUtil.getSessionFactory());
//		} catch (MalformedObjectNameException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
	
	public void initStatistics(SessionFactory sessionFactory) throws MalformedObjectNameException {
	    ObjectName statsName = new ObjectName("org.hibernate:type=statistics");

	    MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
	    
	    final Statistics statistics = sessionFactory.getStatistics();
	    statistics.setStatisticsEnabled(true);
	    InvocationHandler inv = new InvocationHandler() {
	    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	    		return method.invoke(statistics, args);
	    	}
	    };
	    Object statisticsMBean = Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { StatisticsMXBean.class }, inv);
	    

	    try {
			mbeanServer.registerMBean(statisticsMBean, statsName);
		} catch (InstanceAlreadyExistsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MBeanRegistrationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotCompliantMBeanException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void setSessionFactory(SessionFactory sessionFactory) {
		HibernateUtil.sessionFactory = sessionFactory;
	}
	
	public static void findFreshOne(Object o){
		getSessionFactory().openSession().refresh(o);
	}
}
